/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.core.be;

import com.inspur.edp.bef.api.action.IBefCallContext;
import com.inspur.edp.bef.api.action.assembler.IMgrActionAssemblerFactory;
import com.inspur.edp.bef.api.be.BufferClearingType;
import com.inspur.edp.bef.api.be.IBEManager;
import com.inspur.edp.bef.api.be.IBEManagerContext;
import com.inspur.edp.bef.api.be.IBusinessEntity;
import com.inspur.edp.bef.api.lcp.AuthInfo;
import com.inspur.edp.bef.api.lcp.IStandardLcp;
import com.inspur.edp.bef.api.services.IBELogger;
import com.inspur.edp.bef.core.DotNetToJavaStringHelper;
import com.inspur.edp.bef.core.LcpUtil;
import com.inspur.edp.bef.core.action.AuthorityUtil;
import com.inspur.edp.bef.core.action.base.BEMgrActionExecutor;
import com.inspur.edp.bef.core.logger.BefLogger;
import com.inspur.edp.bef.core.session.BEFuncSessionBase;
import com.inspur.edp.bef.core.session.FuncSession;
import com.inspur.edp.bef.core.session.FuncSessionManager;
import com.inspur.edp.commonmodel.core.variable.VarBufferManager;
import com.inspur.edp.bef.spi.extend.IBEManagerExtend;
import com.inspur.edp.cef.api.dataType.entity.ICefRootEntity;
import com.inspur.edp.cef.api.manager.ICefDataTypeManager;
import com.inspur.edp.cef.api.manager.ICefEntityManager;
import com.inspur.edp.cef.api.manager.action.IMgrActionExecutor;
import com.inspur.edp.cef.core.rootmanager.BaseRootManagerContext;
import com.inspur.edp.cef.spi.entity.resourceInfo.EntityResInfo;
import com.inspur.edp.cef.spi.entity.resourceInfo.ModelResInfo;
import com.inspur.edp.cef.variable.api.data.IVariableData;
import com.inspur.edp.cef.variable.api.manager.IVariableManager;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;

import io.iec.edp.caf.runtime.config.CefBeanUtil;
import io.iec.edp.caf.securityentry.api.common.AuthType;
import io.iec.edp.caf.securityentry.api.data.PermissionEntity;
import io.iec.edp.caf.securityentry.api.data.SecurityEntry;
import io.iec.edp.caf.securityentry.api.manager.SecurityEntryService;
import lombok.Getter;
import lombok.Setter;

public final class BEManagerContext extends BaseRootManagerContext implements IBEManagerContext {
		//region 构造函数

	public BEManagerContext(IMgrActionAssemblerFactory mgrActionAssemblerFactory)
	{
		this.privateMgrActionAssemblerFactory = mgrActionAssemblerFactory;
		this.cachedState = false;
		//BEManager = beManager;
	}
		//endregion

		//region 属性字段
	@Getter
	@Setter
	private FuncSession session;

	public BEFuncSessionBase getSessionItem() {
		return (BEFuncSessionBase) session.getSessionItems().get(getBEManager().getBEType());
	}

	private BEManager innerGetBEManager(){return (BEManager)getBEManager();
	}

	@Override
	public IBEManager getBEManager(){return (IBEManager)getRootManager();}

	@Override
	public ICefEntityManager getManager(){return getBEManager();}

	@Override
	public void setManager(ICefDataTypeManager mgr){throw new RuntimeException();}

	private IVariableManager variableManager;
	public IVariableManager getVariableManager() {
		return (variableManager != null) ? variableManager : (variableManager = innerGetBEManager().internalCreateVariableManager());
	}

	public VarBufferManager getVarBufferManager() {
		return getSessionItem() == null ? null : getSessionItem().getVarBufferManager();
	}

	public IVariableData getVariables(){
		VarBufferManager varMgr = getVarBufferManager();
		return varMgr == null ? null : varMgr.getCurrentData();
	}

	@Override
	public HashMap<String, String> getRepoVariables(){return getSessionItem().getRepositoryVariables();}

	public IVariableData getReadonlyVariables() {
		return getVarBufferManager().getReadonlyCurrentData();
	}

	 @Override
	 public BufferClearingType getBufferClearingType(){
return getSessionItem().getBufferClearingType();
	 }
	 @Override
	 public void setBufferClearingType(BufferClearingType value)
	 {
		 getSessionItem().setBufferClearingType(value);
	 }

	 public IBeBufferChangeManager getBufferChangeManager(){
		return getSessionItem().getBufferChangeManager();
	 }

		//endregion

	@Deprecated
	@Override
	public List<IBusinessEntity> getEntities(List<String> ids) {
		return getEntities(ids,true);
	}
	@Deprecated
	@Override
	public List<IBusinessEntity> getEntities(List<String> ids,boolean addDataToCache){
		ArrayList<IBusinessEntity> rez = new ArrayList<>(ids.size());
		for(String id : ids) {
			rez.add(getEntity(id,addDataToCache));
		}
		return rez;
	}

	@Override
	public Map<String, IBusinessEntity> getEntitiesMap(List<String> ids) {
		Map<String, IBusinessEntity> rez = new HashMap<>(ids.size());
		for(String id : ids) {
			rez.put(id, getEntity(id));
		}
		return rez;
	}

	@Override
	public void clearEntities()
	{
		getCacheManager().clearEntities();
	}

	@Override
	public List<IBusinessEntity> getAllEntities() {
		BEFuncSessionBase sessionItem = getSessionItem();
		//TODO:getAllEntities内部new ArrayList, 大数据量时性能弱
		return (List)sessionItem.getBizEntityCacheManager().getAllEntities();
	}

	//TODO:改用getAllEntities()后此方法废弃
	public void consumeAllEntites(Consumer<IBusinessEntity> consumer){
		BEFuncSessionBase sessionItem = getSessionItem();
		for(ICefRootEntity item : sessionItem.getBizEntityCacheManager().getAllEntities()){
			consumer.accept((IBusinessEntity)item);
		}
	}

	@Override
	public IBusinessEntity getEntity(String id) {
		return getEntity(id,true);
	}

	public IBusinessEntity getEntity(String id,boolean addDataToCache) {
		BusinessEntity entity = (BusinessEntity) getCacheManager().getEntity(id,addDataToCache);
		entity.getBEContext().setSessionItem(getSessionItem());

		return entity;

	}
		//region 组装器工厂

	private IMgrActionAssemblerFactory privateMgrActionAssemblerFactory;
	@Override
	public IMgrActionAssemblerFactory getMgrActionAssemblerFactory() {
		return privateMgrActionAssemblerFactory;
	}

		//endregion

	public BizEntityCacheManager getCacheManager()
	{
		return getSessionItem().getBizEntityCacheManager();
	}

	@Override
	public IBELogger getLogger()
	{
		return new BefLogger();
	}

	@Override
	public IStandardLcp getLcp(String config)
	{
		return LcpUtil.getLcp(config);
	}

	//public IStandardLcp getLcp(string config, bool newSession)
	//{
	//    return LcpUtil.getLcp(config,newSession);
	//}

	@Override
	public void checkAuthority(String actionCode) {

		//修改这里
		AuthorityUtil.checkAuthority(actionCode, getSession(), this);
		getSession().getBefContext().setCurrentOperationType(actionCode);
	}
	// 权限信息缓存
	private ConcurrentHashMap<SecurityEntry, ConcurrentHashMap<String, PermissionEntity>> entryActionPermissionMap;

	/**
	 * 根据 SecurityEntry获取 PermissionEntity
	 * @param securityEntry
	 * @param actionCode
	 * @return
	 */
	public PermissionEntity getPermissionEntityByCache(SecurityEntry securityEntry, String actionCode) {
		if(this.entryActionPermissionMap == null) {
			this.entryActionPermissionMap = new ConcurrentHashMap<>();
		}
		ConcurrentHashMap<String, PermissionEntity> permissionEntityMap = this.entryActionPermissionMap.get(securityEntry);
		if(permissionEntityMap == null) {
			permissionEntityMap = new ConcurrentHashMap<>();
		}
		PermissionEntity permissionRez = permissionEntityMap.get(actionCode);
		if(permissionRez == null) {
			SecurityEntryService service = CefBeanUtil.getAppCtx().getBean(SecurityEntryService.class);
			permissionRez = service.getPermission(securityEntry,actionCode);
			// 对 permissionRez 进行缓存
			permissionEntityMap.put(actionCode,permissionRez);
			this.entryActionPermissionMap.put(securityEntry, permissionEntityMap);
//			cacheSecurityEntryAndPermissionEntity(securityEntry,actionCode,permissionRez);
		}
		return permissionRez;
	}

//
//	private  void cacheSecurityEntryAndPermissionEntity(SecurityEntry securityEntry, String actionCode, PermissionEntity permissionRez) {
//		ConcurrentHashMap<String, PermissionEntity> permissionEntityMap = new ConcurrentHashMap<>();
//		permissionEntityMap.put(actionCode,permissionRez);
//		this.entryActionPermissionMap.put(securityEntry,permissionEntityMap);
//	}

	private SecurityEntry authSecurityEntry;
	// 缓存SecurityEntry
	private boolean cachedState;

	public SecurityEntry getSecurityEntry(SecurityEntry entry) {
		if(!this.cachedState) {
			SecurityEntryService securityEntryService= CefBeanUtil.getAppCtx().getBean(SecurityEntryService.class);
			this.authSecurityEntry = securityEntryService.getAuthSecurityEntry(entry);
			this.cachedState = true;
		}
		return this.authSecurityEntry;
	}



//	@Override
//	public ConcurrentHashMap<SecurityEntry, ConcurrentHashMap<String, PermissionEntity>> getEntryActionPermissionMap() {
//		if(entryActionPermissionMap == null) {
//			entryActionPermissionMap =  new ConcurrentHashMap<>();
//		}
//		return  entryActionPermissionMap;
//	}

	/**
	 这个地方需要每次都New，请勿改成单例。

	 <typeparam name="T"></typeparam>
	 @return
	*/

	@Override
	public <T>  IMgrActionExecutor<T> getActionExecutor() {
		BEMgrActionExecutor<T> tempVar = new BEMgrActionExecutor<>(session);
		tempVar.setContext(this);
		return tempVar;
	}


		//region i18n
	@Override
	public ModelResInfo getModelResInfo(){return getBEManager().getModelInfo();}

	public EntityResInfo getEntityResourceInfos(String nodeCode)
	{
		return getModelResInfo().getCustomResource(nodeCode);
	}

	@Override
	public String getEntityI18nName(String nodeCode)
	{
		return getEntityResourceInfos(nodeCode).getDisplayName();
	}

	@Override
	public String getPropertyI18nName(String nodeCode, String labelID)
	{
		String result = getEntityResourceInfos(nodeCode).getPropertyDispalyName(labelID);
		if (DotNetToJavaStringHelper.isNullOrEmpty(result))
		{
			result = labelID;
		}
		return result;
	}

	@Override
	public String getRefPropertyI18nName(String nodeCode, String labelID, String refLabelID)
	{
		return getEntityResourceInfos(nodeCode).getAssoRefPropertyDisplay(labelID, refLabelID);
	}

	@Override
	public String getEnumValueI18nDisplayName(String nodeCode, String labelID, String enumKey)
	{
		return getEntityResourceInfos(nodeCode).getEnumPropertyDispalyValue(labelID, enumKey);
	}

	@Override
	public String getUniqueConstraintMessage(String nodeCode, String conCode)
	{
		return getEntityResourceInfos(nodeCode).getUniqueConstraintMessage(conCode);
	}

	@Override
	public IBefCallContext getCallContext(){
		return getSessionItem().getCallContext();
	}

		//endregion

  //region [运行时定制]扩展
  private List<IBEManagerExtend> extList;

  public final void setExtend(List<IBEManagerExtend> extList) {
    this.extList = extList;
  }
  //endregion


//	public boolean hasOpAuth(String actionCode)
//	{
//		return  getSessionItem().hasOpAuth(actionCode);
//	}
//
//	public void addOpAuth(String actionCode)
//	{
//		getSessionItem().addOpAuth(actionCode);
//	}
}
